iis,nginx keepalive 功能测试。 一、keepalive是什么? 1-1.keepalive概念。 [引用wikipedia]:A keepalive (KA) is a message sent by one device to another to check that the link between the two is operating, or to prevent the link from being broken. keepalive 是两个设备之间,通过发送信息,检测或通信链路是否正常,或防止防止被破坏。 1-2.TCP keepalive [wiki]:Transmission Control Protocol (TCP) keepalives are an optional feature, and if included must default to off.[1] The keepalive packet contains null data. In an Ethernet network, a keepalive frame length is 60 bytes, while the server response to this, also a null data frame, is 54 bytes.[citation needed] There are three parameters[2] related to keepalive: Keepalive time is the duration between two keepalive transmissions in idle condition. TCP keepalive period is required to be configurable and by default is set to no less than 2 hours. Keepalive interval is the duration between two successive keepalive retransmissions, if acknowledgement to the previous keepalive transmission is not received. Keepalive retry is the number of retransmissions to be carried out before declaring that remote end is not available. Tcp keepalive 是TCP协议的一个可选功能,默认关闭。keepalive的数据帧/包不含任何数据。在以太网中,一个keepalive帧长度为60字节。服务器对此的响应也是一个空数据帧,56字节。keepalive有3个参数: keepalive time : 两个处于keepalive链接状态下的设备,允许keepalive链路空闲的最大时间。默认不小于2小时 keepalive interval:是两个keepalive链路的设备,相互确认keepalive时候,发送keepalive帧的时间间隔。 keepalive retry:当相互确认keepalive的帧没有得到响应时候的重试次数。 三者的关系是,一个TCP keepalive链路两边的设备。在相互保持了空闲时间,时间到达keepalive time设定值后,tcp发起方发送keepalive帧确认对方是否存活。如果得不到相应,则经过 keepalive interval设定时间后,再次发送keepalive帧。最多重试keepalive retry设定的次数。 为什么要是用TCP keepalive,对于大并发的服务器,keepalive特别有意义,可以解决TCP握手,挥手所消耗的资源和时间。减少tcp链接数量。 【参考The Linux Documentation Project】:http://www.tldp.org/HOWTO/TCP-Keepalive-HOWTO/index.html 问题:需要有tcp链接池,并对连接池进行管理,才能重用tcp链接。要确认tcp链接当前是否“干净”以免数据发送错乱。 1-3.HTTP keepalive [wiki]:The Hypertext Transfer Protocol uses the keyword "Keep-Alive" in the "Connection" header to signal that the connection should be kept open for further messages (this is the default in HTTP 1.1, but in HTTP 1.0 the default was to use a new connection for each request/reply pair).[6] Despite the similar name, this function is entirely unrelated. HTTP keepalive 是http协议中,重用connection的一种手段方式。HTTP1.1默认开启。HTTP1.0需要在request head中增加connection 关键字,值“Keep-Alive”。 本质上也是对Tcp链接的重用。 综上所述:keepalive 是一种保持两个设备之间通信链路正常的一个概念。TCP协议中包含了keepalive的功能,他主要是一种节约资源提高通信效率的连接复用功能,并且拥有三个参数可调节。HTTP协议本身依托于TCP协议建立Connection,HTTP协议中需要在Request Head中声明是否使用keepalive来保持已经建立的connection。 二、IIS与Nginx中的keepalive 2-1,IIS iis作为一个Web Service 服务器,处理大量的HTTP链接请求。那么必然也会使用到Keepalive。 iis中,在网站的 (IIS7)“HTTP响应头”选项中,“常用响应头”选项内,可以勾选“保持HTTP连接”选项。开启HTTP keepalive功能。默认打开。开启后,request<->reponse之后connection不会被关闭,而是空闲,进入connection池,等待复用。 iis 网站的“高级选项”中->"连接限制"->"连接超时" 设定 http 空闲connection保持的最大时间,超时后关闭。 2-2,Nginx Nginx是一款反向代理 http web服务器软件。可以对接收到的 http request进行代理转发,并可以对后端的upstream server进行负载均衡配置。 所以Nginx的keepalive分两个方面 一个是Client与nginx之间的keepalive,此时nginx相当于WebServer。 另一种是Nginx与upstream server之间的keepalive,此时nginx相当于Client。 Nginx 有三个 keepavlie参数 HTTP -> keepavlie_timeout:conneciton保持空闲的最大时间。默认65。设置0表示关闭。 HTTP -> keepalive_requests: 和client之间保持keepalive connection的最大数量。超过后,会关闭最旧的connection。 upstream -> keepalive: 一个nginx进程与upstream之间保持keepalive connection的最大数量,超过后关闭最旧的connection。 三、iis端测试 3-1,IIS 默认keepalive测试 测试工具:建立网站的iis 7.0 + framewark4.0的应用程序池,浏览器IE,chrome,cmd:netstat 测试目的:确认IIS的keepalive的功能,查看keepalive中的tcp状态,浏览器与keepalive之间的关联,和系统层tcp相关keepalive的关联。获得浏览器与iis之间保持keepalive的典型特征。 【注】一个完整的tcp链接,在client端与server端设备上查看时,应该各有一个tcp链接记录。这两个tcp的源ip:端口与目的ip:端口是对应的。 测试方案: (1)确认打开keepalive功能后,使用浏览器打开页面,然后查tcp状态。关闭标签,关闭浏览器后,tcp链接状态。 (2)在一个浏览器中打开多个标签,查看tcp状态 (3)打开多个标签后,刷新标签,查看tcp状态。确认链接复用。 (4)在保持keepalive的状态下,iis重启。查看tcp状态。 测试过程记录: (1)当打开标签请求页面后,ie与iis之间建立了一条tcp,请求完成后,tcp依旧保持在ESTABLISHED状态。关闭标签,tcp还在。关闭浏览器,tcp消失。 (2)先在一个浏览器中,打开了5个标签。查看tcp共建立了4条tcp链接,都处于keepalive,比预想的少一条。后发现资源管理器中,只有4个IE标签的进程。 在一个浏览器中,打开了10个标签,查看得到7个tcp链接都处于keepalive,也比预想的少。 关闭浏览器,浏览器端TCP链接全部消失,iis端有一条tcp处于TIME_WAIT状态。 (3)逐一打开5个标签,详细:标签 <-> :Tcp链接端口号 Label1<->:50008 Label2<->:50016 Label3<->:50022 Label4<->:50026 Label5<->:50030 当打开第五个标签时候, Label1<->:50008 IE的TCP状态处于 TIME_WAIT IIS Server端 只有keepalive的4个链接。 刷新Label1,4条TCP状态不变保持ESTABLISHED。 刷新Label2~5,50030复用,新建50039,50041,50043三条tcp链接,其余tcp消失释放 刷新Label1~5,4条Tcp全部复用。 (4)5个Label。保持4条tcp情况下,cmd输入命令iisreset,IE端连接消失释放,iis端4条链接全部转Time_wait状态,查看进程id后,4条链接所属进程号0,PID 0 为系统idle进程,windows下的孤儿进程。 测试结果和疑问 【结1】过程2中,链接数量和标签数量不一致,说明tcp的建立应该与标签并不是1对1,或者多对1的关系,也可以是1对多。说明ie和chrome在默认设置中,都可能对tcp链接启用了连接池,并统一管理。 【结2】http保持keepalive是tcp是处于ESTABLISHED状态,通信状态。但没有任何数据推送。(抓包监控得出) 【结3】iis的keepalive和预期一样起了作用。tcp的链接数和浏览器进程(client数量)数量相同。 【结4】各自关闭程序进程,iis重启,原有Keepalive状态的下tcp大多都会消失,说明不论是client端还是server端,各自都有能力主动关闭keepalive中的tcp,并且发送fin信号给对方,通知对方关闭。但tcp的的真正释放,是由系统管理的。 【结5】关闭进程后失去主进程的tcp状态变成TIME_WAIT.处于pid0进程收养下,推测tcp链接作为外部资源,累死java/C#不能由程序直接释放,要交由系统层来进行释放处理。 【问1】ESTABLISHED对系统的消耗是高于Wait状态的。过多的keepalive对资源回收利用是不是不利?极高并发下使用keepalive是否不利? 【问2】为什么浏览器进程数量和标签数量不一致,总是少一两个?是不是有的标签在浏览器父进程内? 3-2,iis 关闭keepalive后测试 测试目的:查看没有keepalive情况下,tcp的生命周期。 测试方案: (1)关闭iis中的“保持HTTP连接” (2)使用ie/chrome 打开一个标签正常访问iis,并查看tcp链接情况 (3)保持1个标签,多次刷新,查看tcp情况 (4)打开多个标签,全部刷新一次,查看tcp情况。 测试过程记录: (1)确认关闭iis的keepalive后,打开1个浏览器标签访问iis页面。刷新成功后,Server端tcp处于Time_wait,Client端Tcp已经消失。 (2)等系统释放tcp后。将刚才的标签刷新5次,11次,刷新成功。Server端分别留有5个,11个tcp链接,且处于Time_wait状态,pid=0收养。Client端无残留tcp。 (3)等待tcp系统释放后。打开4个标签,各刷新一次。Server端共留有8个待系统释放的tcp。client端无连接。 测试结果和疑问 【结1】当iis不支持keepalive,浏览器端也不会使用keepalive(仅浏览器,不代表其他程序) 【结2】每一次http request response 都建立一条tcp连接。当完成http处理后,双方都立即释放连接。 【问1】当大并请求发情况下,系统tcp释放是否会跟不上速度,产生大量pid0 TimeWait的Tcp,造成资源不够。 3-3,开启iis端 keepalive,设定超时时间30秒进行测试。 测试目的:测试保持连接测超时时间,与keepalive的等待时间,是否有关联。超时参数起作用的表现形式。 测试方案: (1)浏览器中打开一个标签访问iis后,监控tcp情况。并一直等到tcp连接被释放。 (2)确认tcp释放后,刷新标签,观测tcp情况。 (3)打开两个标签,查看tcp情况 (4)打开多个标签,查看tcp情况。 (5)在tcp保持keepalive时,iis中关闭keepalive,继续刷新之前的标签。 测试过程记录: (1)打开标签后,client与server两端各有一条tcp处于Estab状态,等待超过30秒后,两段tcp直接消失(被释放) (2)再次刷新标签,C自新建一条tcp,并处于estab。 tcp:50202 (3)增加一个标签后,出现两条处于estab的tcp。tcp:50202和tcp:50212。再刷新之前的标签,等到至超时,tcp:50212先消失。tcp:50202后消失 (4)新建加到5个标签,并刷新。总共4条tcp链接保持keepalive,都在30秒后左右时间消失。 (5)关闭iis的keepalive后,tcp全部处于timewait。刷新标签有可能出现卡顿(1次,可能只是ie卡了),刷新都新建tcp。 测试结果和疑问: 【结1】iis的链接“最大空闲时间”这个参数还是非常准确的。但感觉上实际释放tcp的链接比设定的30秒长。 【结2】新建标签是,tcp没有复用。tcp的复用应该还是和浏览器进程数量有关,需要测试浏览器的tcp pool机制 【问1】开启keepalive后,超时关闭的tcp,没有出现过timewait,pid0孤儿化之类的 资源等待释放现象。推测为处于通信中的tcp关闭连接比较正常。关闭浏览器,iis重启,造成的tcp孤儿话,等待释放的现象,可能是tcp宿主线程,还没等对方进行确认,就自己关闭了tcp。导致fin,ack没有回复。 四、Nginx与client之间的测试 Nginx作为webserver,反向代理服务器,自身也有处理http请求的能力。和keepalive相关的有:keepavlie_timeout,keepalive_requests,两个server/http/location参数,以及upstream中的keepalive参数。总共三个。 4-1,nginx与浏览器keepalive测试。 测试目的:了解nginx作为web site server ,对http的keepalive支持表现 测试方案:类同于iis与client之间。 (1)浏览器打开一个标签,刷新,观察tcp状态。 (2)关闭浏览器,观察tcp状态。 (3)打开多个标签,查看tcp状态。 测试过程:与iis的测试保持一致。 (1)当打开一个标签时,打开后,刷新页面,均保持一个tcp链接。 (2)保持tcp时关闭浏览器,client与server端的tcp都同时消失。 (3)打开5个标签,任就只有4条保持keepalive的tcp。 测试结果: 【结1】nginx作为server,与iis基本一致。都能支持http协议的keepalive。 【结2】多次实验都未出现server端tcp处于waittime/closewait状态,或许linux系统下,对tcp的回收释放机制比较及时,也可能nginx对这个处理比较好。 【结3】多个标签,tcp数量与之前实验一致,或许验证了,tcp数量与client进程有关,与标签无关。 4-2,nginx,keepalive tomeout参数测试 测试目的:验证nginx控制的keepalive时间,与linux系统中tcp的keepalive超时时间的区别 测试方案: (1)打开多个标签,监控tcp状态,同时只刷新一个标签。等到超时后,观测tcp的变化情况。 (2)链接状态下,直接关闭浏览器,观测tcp状态。 (3)调整keepalive_timeout 为30秒,打开刷新浏览器,等待超时,观测tcp (4)调整keepalive_timeout 为0秒(关闭keepalive),打开刷新浏览器,观测tcp (5)保持连接状态下,nginx reload重启 测试过程: (1)打开4个标签,只间断刷新一个标签。超过70多秒后,仅剩下一条tcp保持estab,其余tcp均处于close_wait (2)打开多个标签,监控多个tcp状态直至超时。 超时状态表现为:client端(IE) close_wait / Last_Ack server端(nginx) Fin_wait2 / Time_wait 超时tcp变化过程: IE端 | nginx端 close_wait ----> Fin_wait2 | Last_Ack <---- Time_wait | 消失(释放) <----> Time_wait (3)保持连接状态下,直接关闭浏览器,两端tcp都直接消失。 (4)调整timeout时间为30s,观察tcp状态变化,得到结果,tcp链接约在30秒多一些时候关闭。 (5)调整timeout时间为0,观测tcp状态。得道结果在关闭nginx的keepalive情况下,刷新一次页面,均产生一个新的tcp链接。并且http通信结束后,server端与client端的tcp都一样,数据传输一结束tcp立即处于Time_wait状态。已被程序释放。系统但系统未释放资源。 (6)保持连接式,软重启nginx,Server端的tcp都被系统收养,并处于Fin_Wait2.同时,Client端,tcp_处于close_wait 测试结论: 【结1】timeout参数对超时时间的控制比较精准。 【结2】关闭nginx的keepalive,结果与iis比较类似。相同在于每一次访问都使用一个新的tcp,结束后server端tcp立刻处于等待系统回收阶段。不同在于,iis的client端tcp被系统直接释放。而nginx的client端tcp是被系统收养。 【问3】推测,nginx收到client段发送来的关闭信号,释放比较彻底。所以在关闭浏览器时候,tcp释放比较干净。而超时主动关闭tcp时候处理处理就拖泥带水了。详细需要抓包查看。再下定论。 4-3,nginx,与iis之间的keepalive测试 测试目的: nginx pstream中的keepalive。nginx做反向代理是。是作为client端向webservice转发http请求。nginx默认是不开启upstream的keepalive。 作为client端开启keepalive需要在upstream中设置这个参数,且大于0。并且在request_head中写入 connection=“keep-alive”或者使用http1.1版本。【注:http1.1默认开启keepalive。但http1.0版本需要手工添加】 nginx官网对keepalive这个参数的说明是,每个nginx process维持upstream对象群的keepalive链接的的最大数。超过这个数,则开始关闭最久的tcp。保护upstream被过多的keepalive tcp占用资源。 本测试目的是为了搞清楚,nginx代理iis时,如何开启keepalive的前提。 测试方案: (1)iis关闭keepalive,nginx 相关的参数,查看tcp情况 (2)iis开启keepalive,nginx相关参数keepalive_timeout变化。观察tcp情况 (3)iis开启keepalive,nginx,upstream{keepalive}参数设置变化。观察tcp情况。 测试过程: (1)当iis关闭keepalive时,当nginx的keepavlie_timeout设置为0s,打开网页标签,tcp都是立即被释放。 nginx是tcp立即处于close_wait。iis则是tcp已被系统释放。 (2)更改keepalive_timeout设置为65s时。 nginx的tcp立即关闭,被系统释放。iis则是大量处于time_wait的孤儿连接(被iis释放,系统未释放) (3)设置keepalive_timeout=30s,http 版本1.1,在代理中开启keepalive。iis保持关闭keepalive 情况同上,nginx的tcp,立即被系统释放。iis的tcp处于time_wait (4)当iis开启keepalive,设置超时为120s时。 nginx keepalive_timeout=30s,upstream{keepalive=0} 情况同上 (5)iis开启keepalive,超时30s,nginx设置timeout30s,upstream keepalive=2 打开浏览器,访问nginx代理iis的页面。 标签数为1,2,10的情况时,nginx与iis之间均只有1条tcp且保持ESTAB状态。keepalive 关闭浏览器,再打开浏览器访问页面。关闭浏览器,更换其他浏览器访问页面。nginx与iis之间仍旧保持1条tcp 测试结论: 【结1】由(5)可以得出,nginx与iis保持keepalive的前提iis开启keepalive,nginx必须在upstream中设置keepalive数量大于0,且必须在代理的request head中设置http版本1.1 或增 connection=keepalive 内容.nginx自身的 keepalive_timeout,keepalive_requests 并不作用于 nginx代理的keepalive。 【结2】nginx与iis之间的keepalive链接相当稳定。 4-4,nginx,iis保持keepalive时,tcp链接终止测试。 测试目的: 在试验搞清楚nginx代理iis之间如何使用keepalive的前提条件后。通过参数设置,去影响keepalive。或者模拟外部异常,终止keepalive的情况。 测试方案: (1)在保持keepalive时,对iis,nginx相应的超时参数进行测试。 (2)在保持keepalive时,nginx和iis进行多种终止服务的操作行为。并观察tcp情况。 比较遗憾,未能测试高压力下的情况 测试过程: (1)iis开启keepalive,timeout30s。nginx upstream:keepalive=2,timeout30s 保持1个keepalive的tcp链接 等待约35秒后,双方的tcp同时释放消失。 iis设置timeout 15秒。等待约18秒后双方tcp消失。 iis设置35秒,nginx设置15秒。等待约40秒后,双方tcp消失。 (2)保持keepalive后, 对iisreset, iis端原有tcp全部消失释放。nginx端的tcp全部变为,time_wait. nginx -s stop iis端tcp消失,nginx端的tcp变为 Time_wait 孤儿化。 nginx 再开启 iis 一个正常ESTAB tcp,Nginx端也是一个正常的tcp。原time_wait的tcp还在,系统未释放。 nginx kill 9 结果和上面一样 iis端还保持一个ESTAB tcp,nginx端是一个正常的tcp。原time_wait的tcp还在,系统未释放。 iis重启网站 网站关闭时,iis与nginx两端的tcp都消失。网站在启动后,两端建立一个ESTAB的正常tcp。 iis的应用程序池回收。 iis与nginx两端的正在保持ESTAB的tcp未收到影响,未变化。 iis应用程序池关闭 iis端tcp处于time_wait,nginx端的tcp释放消失。 测试结论: 【结1】nginx作为代理时,keepalive的超时回收,是根据iis的设置。nginx的超时是不起作用的。nginx的超时仅仅针对与nginx相连的客户端。 【结2】nginx与iis之间,双方服务启动后,就会建立tcp keepalive 【结3】iis的网站服务管理着tcp池,应用程序池回收并不影响tcp连接。 【结4】直接杀进程的方式,保持keepalive的tcp并不会立即变更状态,需要系统发现,处理。容易造成占用问题。 【问1】未作压力测试,无法测得nginx与iis的tcp keepalive数量。